/*
 * main.cpp
 *
 *  Created on: Mar 14, 2013
 *      Author: nick
 */

#include "../h/Logger.h"
#include <boost/iostreams/device/mapped_file.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/iostreams/positioning.hpp>
#include <vector>
#include <string>
#include <iostream>
#include <fstream>
#include <ctime>
#include <cstdlib>

using boost::iostreams::mapped_file_source;
using boost::iostreams::mapped_file_sink;
using boost::iostreams::mapped_file_params;
using boost::spirit::qi::phrase_parse;
using boost::spirit::qi::double_;
using boost::spirit::qi::space;
using boost::iostreams::position_to_offset;
using std::vector;
using std::string;
using std::to_string;
using std::cout;
using std::sort;
using std::ostringstream;


struct DoubleComparator {
	bool operator()(double first, double second) {
		return first < second;
	}
} doubleComparator;

void generateLargeFile();

void getFileSize(std::fstream & fileStream) {
	fileStream.seekg(0, std::ios::beg);
	std::istream::pos_type begin = fileStream.tellg();
	fileStream.seekg(0, std::ios::end);

}

int main(int argc, char* argv[]) {
	mapped_file_source inputFile;
	try {
		inputFile.open(argv[1]);
		string inputString(inputFile.data());
		vector<double> v;
		string::iterator begin = inputString.begin();
		phrase_parse(begin, inputString.end(), double_ % ',', space, v);
		if(begin != inputString.end()) {
			Logging::warn("Your csv file is broken. Reading only " + std::to_string(v.size()) + string(" elements."));
		}
		sort(v.begin(), v.end(), doubleComparator);

		ostringstream stringstream;
		stringstream << *(v.begin());
		for(vector<double>::const_iterator i = v.begin() + 1; i != v.end(); i++) {
			stringstream << ',' << *i;
		}

		char* outputFileName = "output";
		if(argc == 3)
			outputFileName = argv[2];

		mapped_file_params params(outputFileName);

		stringstream.seekp(0, std::ios_base::end);
		params.new_file_size = position_to_offset(stringstream.tellp());
		stringstream.seekp(0, std::ios_base::beg);
		mapped_file_sink outputFile;
		outputFile.open(params);
		memcpy(outputFile.data(), stringstream.str().c_str(), params.new_file_size);

		stringstream.clear();

		inputFile.close();
		outputFile.close();
	} catch(std::exception & e) {
		Logging::error(e.what());
		return EXIT_FAILURE;
	}
	return EXIT_SUCCESS;
}

long long MAX_FILE_SIZE_IN_BYTES = 1024LL*1024LL*1024LL*16LL;

void generateLargeFile() {
	std::ofstream unSortedFile("input", std::ios_base::app | std::ios_base::out);
	srand(time(0));
	if(unSortedFile.tellp() < MAX_FILE_SIZE_IN_BYTES)
		unSortedFile << rand();
	while(unSortedFile.tellp() < MAX_FILE_SIZE_IN_BYTES) {
		unSortedFile << "," << rand();
	}
	ostringstream stringstream;
	stringstream << unSortedFile.tellp();
	Logging::info(string("Total file size ") + stringstream.str() + string(" bytes"));
	unSortedFile.close();
}
